from datetime import timedelta, datetime
from flask import Blueprint, request, current_app, session
from flask_jwt_extended import create_access_token
from util.result import Result
from models import db, User, Role  # 导入 Role 模型，用于查询管理员角色

api_bp = Blueprint('auth', __name__)


# 注册路由
@api_bp.route('/register', methods=['POST'])
def register():
    try:
        data = request.get_json()
        if not data:
            return Result.error("请输入注册信息")

        required_fields = ['username', 'password']
        for field in required_fields:
            if field not in data or not data[field]:
                return Result.error(f"{field} 是必填项")

        # 1. 检查用户名是否已存在
        if User.query.filter_by(username=data['username']).first():
            return Result.error("用户名已存在")

        # 2. 创建用户并关联管理员角色
        user = User(
            username=data['username'],
            role_id=1,
            status=1,  # 默认设置为正常状态（1-正常，0-禁用）
            created_at=datetime.now(),
        )
        user.set_password(data['password'])  # 密码加密存储

        # 3. 提交数据库
        db.session.add(user)
        db.session.commit()

        # 4. 返回成功响应
        return Result.success("注册成功")

    except Exception as e:
        db.session.rollback()  # 异常时回滚事务，避免数据脏写
        current_app.logger.error(f"注册异常: {str(e)}")  # 记录错误日志，便于排查
        return Result.error(f"注册失败: {str(e)}")


# 登录路由
@api_bp.route('/login', methods=['POST'])
def login():
    try:
        data = request.get_json()
        if not data:
            return Result.error("请输入账号密码及验证码")

        # 1. 验证码验证（新增逻辑）
        user_captcha = data.get('captcha').strip().lower()
        captcha_info = session.get('captcha_info')

        # 1.1 验证码参数校验
        if not user_captcha:
            return Result.error("请输入验证码")

        # 1.2 验证码存在性校验
        if not captcha_info:
            return Result.error("验证码已过期，请重新获取")

        # 1.3 验证码时效性校验
        expire_time = captcha_info.get('expire_time')
        try:
            # 字符串转 datetime
            expire_datetime = datetime.strptime(expire_time, "%Y-%m-%d %H:%M:%S")
        except ValueError:
                # 防止时间格式异常
                session.pop('captcha_info', None)
                return Result.error("验证码格式异常，请重新获取")

        # 比较时效性
        if datetime.now() > expire_datetime:
            session.pop('captcha_info', None)
            return Result.error("验证码已过期，请重新获取")

        # 1.4 验证码正确性校验
        if user_captcha != captcha_info.get('text'):
            return Result.error("验证码错误，请重新输入")

        # 2. 验证账号存在性和密码正确性
        user = User.query.filter_by(username=data.get('username')).first()
        if not user or not user.verify_password(data.get('password')):
            return Result.error("账号密码错误")

        # 3. 验证用户状态
        if user.status != 1:
            return Result.error("账号已被禁用，请联系管理员")

        # 4. 生成 JWT Token
        access_token = create_access_token(
            identity=str(user.id),
            expires_delta=current_app.config.get('JWT_ACCESS_TOKEN_EXPIRES', timedelta(hours=1))
        )

        # 5. 获取角色权限
        role = Role.query.get(user.role_id) if user.role_id else None
        permissions = [perm.name for perm in role.permissions] if role else []

        # 6. 构建返回数据
        user_data = {
            "id": user.id,
            "username": user.username,
            "name": user.name,
            "gender": user.gender,
            "age": user.age,
            "phone": user.phone,
            "email": user.email,
            "avatar": user.avatar,
            "role_name": Role.query.get(user.role_id).name if user.role_id else None,
            'permissions': permissions,
        }

        # 7. 验证成功后清除验证码
        session.pop('captcha_info', None)

        return Result.success(
            "登录成功",
            data={"token": access_token, "user": user_data}
        )

    except Exception as e:
        current_app.logger.error(f'登录异常: {str(e)}')
        return Result.error(f"登录失败: {str(e)}")
